package com.gitee.l0km.xthrift.mq.json;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.AbstractDateDeserializer;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.util.TypeUtils;

/**
 * ISO8601日期格式字符序列化/反序列化实现
 * @author guyadong
 * @since 1.4.0
 *
 */
public class Iso8601DateCodec extends AbstractDateDeserializer implements ObjectSerializer, ObjectDeserializer{
    /** ISO8601时间格式 */
    private static final String ISO8601_FORMATTER_STR = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
    private static final String ISO8601_FORMATTER_Z_STR = "yyyy-MM-dd'T'HH:mm:ss'Z'";
	public Iso8601DateCodec() {
	}
	@Override
	public int getFastMatchToken() {
		return JSONToken.LITERAL_STRING;
	}
	@Override
	public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) {
		if (object == null) {
			serializer.out.writeNull();
			return;
		}

		Date date = (Date) object;
		SimpleDateFormat format = new SimpleDateFormat(ISO8601_FORMATTER_Z_STR);
		format.setTimeZone(TimeZone.getTimeZone("UTC"));

		String text = format.format(date);
		serializer.write(text);
	}
	@SuppressWarnings("unchecked")
	@Override
	protected <T> T cast(DefaultJSONParser parser, Type clazz, Object fieldName, Object value) {

        if (value == null) {
            return null;
        }

        if (value instanceof java.util.Date) {
            return (T) value;
        } else if (value instanceof BigDecimal) {
            return (T) new java.util.Date(TypeUtils.longValue((BigDecimal) value));
        } else if (value instanceof Number) {
            return (T) new java.util.Date(((Number) value).longValue());
        } else if (value instanceof String) {
            String s = (String) value;
            
            if (s.length() == 0) {
                return null;
            }
            try {
            	SimpleDateFormat format ;
            	if(s.charAt(s.length()-1) == 'Z') {
            		format= new SimpleDateFormat(ISO8601_FORMATTER_Z_STR);
            		format.setTimeZone(TimeZone.getTimeZone("UTC"));
            	}else {
            		format = new SimpleDateFormat(ISO8601_FORMATTER_STR);
				}
				return (T) format.parse(s);
			} catch (ParseException e) {
				throw new JSONException("FAIL TO PARSE [" + s+"]",e);
			}
        }
        throw new JSONException("parse error");
    }

}
